#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory>
#include <functional>
#include "Common.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace LogModule;

#define SIZE 1024

// 普通sockfd的封装，负责非阻塞模式下的网络数据收发、异常处理等 IO 操作
class Channel : public Connection
{
public:
    Channel(int sockfd, const InetAddr &client) : _sockfd(sockfd), _client_addr(client)
    {
        SetNonBlock(_sockfd);// 将socket设置为非阻塞模式
    }

    // 问题1: 怎么保证我把本轮数据读取完毕？ while 循环 --- 本层只解决IO问题 --- done
    // 问题2：即便是你把本轮数据读完，你怎么知道数据就有完整的报文，如果不完整呢？如果是多个报文呢？粘报问题？反序列化 --- 引入协议的
    
	//负责从sockfd读取数据到输入缓冲区_inbuffer，并触发业务处理。
	void Recver() override
    {
        // 我们读到的是字符串
        char buffer[SIZE];
		//非阻塞模式下，单次recv可能无法读完所有数据，需要循环读取
        while (true)
        {
            buffer[0] = 0;                                            // 清空字符串
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0); // 非阻塞读取的
            if (n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer; // 接受缓冲区中，入队列的过程
            }
            else if (n == 0)
            {
                Excepter();//清理连接
                return;
            }
            else
            {	//非阻塞模式下数据未准备好，退出循环
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    break;
                }
				//读取被信号中断，继续循环重试
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    Excepter();
                    return;
                }
            }
        }
        LOG(LogLevel::DEBUG) << "Channel: Inbuffer:\n"
                             << _inbuffer;
		//数据接收完成后，通过_handler处理_inbuffer中的数据（如解析协议、处理业务）
		//结果存入_outbuffer，并调用Sender()发送响应
        if (!_inbuffer.empty())
            _outbuffer += _handler(_inbuffer); // 和protocol相关的匿名函数里面！

        if (!_outbuffer.empty())
        {
            Sender(); // 最佳实践
            //GetOwner()->EnableReadWrite(_sockfd, true, true);
        }
       
    }

	//将输出缓冲区_outbuffer中的数据发送给客户端
    void Sender() override
    {
        while (true)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if (n > 0)
            {//发送成功，从_outbuffer中删除已发送的部分（erase(0, n)）
                _outbuffer.erase(0, n);
                if (_outbuffer.empty())
                    break;
            }
            else if (n == 0)
            {
                break;
            }
            else
            {//非阻塞模式下发送缓冲区满，退出循环（等待下次可写事件触发再发）
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
			//发送被信号中断，继续循环重试
                if (errno == EINTR)
                    continue;
                else
                {
                    Excepter();
                    return;
                }
            }
        }

        // 1. 数据发送完毕
        // 2. 发送条件不具备
        if (!_outbuffer.empty())
        {
            // 开启对写事件的关心
			//若_outbuffer仍有数据未发完：注册 “写事件”（下次可写时继续发送）
            GetOwner()->EnableReadWrite(_sockfd, true, true);
        }
        else
        {
			//若_outbuffer为空：取消 “写事件” 监听（避免无意义的事件触发）
            GetOwner()->EnableReadWrite(_sockfd, true, false);
        }
    }

    void Excepter() override
    {
        // 所有的异常，都被我归一到了这个函数内部！！
		//统一处理连接异常（如客户端断开、读写错误）
		//通知上层的连接管理器（如Epoll或Poll模块）删除当前连接，
		//释放资源（关闭sockfd、清理事件等）
        GetOwner()->DelConnection(_sockfd);
    }
	
    int GetSockFd() override
    {
        return _sockfd;
    }
    std::string &Inbuffer()
    {
        return _inbuffer;
    }
    void AppendOutBuffer(const std::string &out)
    {
        _outbuffer += out;
    }
    ~Channel()
    {
    }

private:
    int _sockfd;
    std::string _inbuffer; // 充当缓冲区，vector<char>
    std::string _outbuffer;
    InetAddr _client_addr;

    // handler_t _handler;
};